package org.kernely.stream.userpage;

import java.util.Date;

import org.kernely.stream.StreamBundle;
import org.kernely.stream.utils.KernelyMessageTable;
import org.kernely.ui.mvp.IKernelyView;
import org.kernely.ui.mvp.KernelyEventSender;

import com.vaadin.terminal.ExternalResource;
import com.vaadin.terminal.Sizeable;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.Embedded;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.NativeSelect;
import com.vaadin.ui.Panel;
import com.vaadin.ui.ProgressIndicator;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.AbstractTextField.TextChangeEventMode;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.themes.Reindeer;

/**
 * The view displaying the messages of streams.
 */
public class StreamMessagesView extends HorizontalLayout implements IKernelyView, KernelyEventSender{

	/**
	 * Serial version ID
	 */
	private static final long serialVersionUID = -6728075455240022394L;

	private Panel postPanel;
	private Panel postCommentPanel;

	private HorizontalLayout postLayout;
	private HorizontalLayout buttonsLayout;
	private HorizontalLayout buttonsCommentLayout;

	private VerticalLayout moreResultLayout;
	private VerticalLayout detailsLayout;
	private VerticalLayout advancedOptionsLayout;

	private Button streamSettingsButton;
	private Button postButton;
	private Button moreResults;
	private Button postCommentButton;
	private Button clearStreamSearch;
	private Button advancedOptionsButton;

	private TextField inputMessage;
	private TextField inputComment;
	private TextField streamSearchText;

	private Label lengthLabel;
	private Label infoLabel;
	private Label messageContent;
	private Label streamName;
	private Label infoCommentLabel;
	private Label lengthCommentLabel;
	private Label messageDisplayed;

	private NativeSelect streamsBox;
	private NativeSelect streamFilterBox;

	private KernelyMessageTable messageTable;
	private KernelyMessageTable commentTable;

	private CheckBox commentableMessage;

	/**
	 * StreamUserPageView constructor
	 */
	@SuppressWarnings("serial")
	public StreamMessagesView(){
		streamsBox = new NativeSelect();
		streamsBox.setNullSelectionAllowed(false);

		// Artisanal pool system.
		ProgressIndicator poolMessages = new ProgressIndicator();
		poolMessages.setIndeterminate(true);
		poolMessages.setEnabled(true);
		poolMessages.setVisible(true);
		poolMessages.setPollingInterval(5000);


		postPanel = new Panel();
		postPanel.setSizeFull();


		inputMessage = new TextField();		
		inputMessage.setSizeFull();
		inputMessage.setHeight(25, Sizeable.UNITS_PIXELS);
		inputMessage.setTextChangeEventMode(TextChangeEventMode.LAZY);
		inputMessage.setTextChangeTimeout(50);
		inputMessage.setImmediate(true);

		buttonsLayout = new HorizontalLayout();
		buttonsLayout.setSizeFull();

		lengthLabel = new Label();
		lengthLabel.setImmediate(true);

		infoLabel = new Label();
		infoLabel.setContentMode(Label.CONTENT_XHTML);
		infoLabel.setImmediate(true);

		postButton = new Button("Post");
		postButton.setImmediate(true);
		postButton.setEnabled(false);

		streamSettingsButton = new Button();
		streamSettingsButton.setIcon(new ExternalResource("/streambundle/images/custom.png"));

		streamFilterBox = new NativeSelect();
		streamFilterBox.setNullSelectionAllowed(false);
		streamFilterBox.setImmediate(true);

		streamSearchText = new TextField();
		streamSearchText.setTextChangeEventMode(TextChangeEventMode.LAZY);
		streamSearchText.setTextChangeTimeout(500);
		streamSearchText.setImmediate(true);
		streamSearchText.setInputPrompt("Search...");

		clearStreamSearch = new Button("Clear");
		clearStreamSearch.addListener(new ClickListener() {
			/**
			 * @see com.vaadin.ui.Button.ClickListener#buttonClick(com.vaadin.ui.Button.ClickEvent)
			 */
			public void buttonClick(ClickEvent event) {
				streamSearchText.setValue("");
			}
		});

		moreResults = new Button("More results");
		moreResultLayout = new VerticalLayout();
		moreResultLayout.setSizeFull();
		moreResultLayout.addComponent(moreResults);
		moreResultLayout.setComponentAlignment(moreResults, Alignment.MIDDLE_CENTER);

		postPanel.addComponent(inputMessage);
		postPanel.addComponent(buttonsLayout);

		advancedOptionsButton = new Button("Advanced options");
		advancedOptionsButton.setImmediate(true);
		advancedOptionsButton.addListener(new ClickListener() {
			/**
			 * @see com.vaadin.ui.Button.ClickListener#buttonClick(com.vaadin.ui.Button.ClickEvent)
			 */
			public void buttonClick(ClickEvent event) {
				if(!advancedOptionsLayout.isVisible()){
					advancedOptionsButton.setCaption("Classic options");
					advancedOptionsLayout.setVisible(true);
				}
				else{
					advancedOptionsButton.setCaption("Advanced options");
					advancedOptionsLayout.setVisible(false);
				}
			}
		});

		commentableMessage = new CheckBox("Authorize comments");
		commentableMessage.setValue(true);

		advancedOptionsLayout = new VerticalLayout();
		advancedOptionsLayout.setVisible(false);
		advancedOptionsLayout.setSpacing(true);


		advancedOptionsLayout.addComponent(streamsBox);
		advancedOptionsLayout.addComponent(commentableMessage);
		advancedOptionsLayout.setMargin(true, false, false, false);

		postLayout = new HorizontalLayout();
		postLayout.setSizeUndefined();
		postLayout.setSpacing(true);
		postLayout.addComponent(advancedOptionsButton);
		postLayout.addComponent(postButton);

		postPanel.addComponent(advancedOptionsLayout);

		buttonsLayout.addComponent(lengthLabel);
		buttonsLayout.addComponent(infoLabel);
		buttonsLayout.addComponent(postLayout);

		buttonsLayout.setComponentAlignment(lengthLabel, Alignment.MIDDLE_CENTER);
		buttonsLayout.setComponentAlignment(postLayout, Alignment.MIDDLE_RIGHT);
		buttonsLayout.setMargin(true, false, false, false);

		messageTable = new KernelyMessageTable(false);

		streamName = new Label("Details");
		streamName.setStyleName(Reindeer.LABEL_H2);
		streamName.setSizeUndefined();

		messageContent = new Label("Click on a message to see its details.");
		messageContent.setContentMode(Label.CONTENT_XHTML);


		commentTable = new KernelyMessageTable(true);
//		commentTable.addStyleName(Reindeer.TABLE_BORDERLESS);
		commentTable.setCellStyleGenerator(new Table.CellStyleGenerator() {
			/**
			 * @see com.vaadin.ui.Table.CellStyleGenerator#getStyle(java.lang.Object, java.lang.Object)
			 */
			public String getStyle(Object itemId, Object propertyId) {
				return "messages";
			}
		});


		detailsLayout = new VerticalLayout();
		detailsLayout.setSizeFull();
		detailsLayout.setSpacing(true);
		detailsLayout.setMargin(true);
		detailsLayout.setImmediate(true);

		detailsLayout.addComponent(streamName);
		detailsLayout.addComponent(messageContent);
		detailsLayout.addComponent(commentTable);

		detailsLayout.setComponentAlignment(streamName, Alignment.MIDDLE_CENTER);

		VerticalLayout messagesLayout = new VerticalLayout();
		HorizontalLayout buttonsLayout = new HorizontalLayout();
		buttonsLayout.setSpacing(true);
		buttonsLayout.addComponent(streamSearchText);
		buttonsLayout.addComponent(clearStreamSearch);
		buttonsLayout.addComponent(streamFilterBox);
		buttonsLayout.addComponent(streamSettingsButton);
		buttonsLayout.setSizeUndefined();
		messagesLayout.addComponent(buttonsLayout);
		messagesLayout.setComponentAlignment(buttonsLayout, Alignment.MIDDLE_RIGHT);
		messagesLayout.addComponent(postPanel);
		messagesLayout.addComponent(messageTable);
		messagesLayout.addComponent(moreResultLayout);
		messagesLayout.setSizeFull();
		messagesLayout.setMargin(true);
		messagesLayout.setSpacing(true);


		postCommentPanel = new Panel();

		inputComment = new TextField();
		inputComment.setSizeFull();
		inputComment.setHeight(25, Sizeable.UNITS_PIXELS);
		inputComment.setTextChangeEventMode(TextChangeEventMode.LAZY);
		inputComment.setTextChangeTimeout(50);
		inputComment.setImmediate(true);
		buttonsCommentLayout = new HorizontalLayout();
		buttonsCommentLayout.setSizeFull();
		lengthCommentLabel = new Label();
		lengthCommentLabel.setImmediate(true);

		infoCommentLabel = new Label();
		infoCommentLabel.setContentMode(Label.CONTENT_XHTML);
		infoCommentLabel.setImmediate(true);

		postCommentButton = new Button("Comment");
		postCommentButton.setImmediate(true);
		postCommentButton.setEnabled(false);

		postCommentPanel.addComponent(inputComment);
		postCommentPanel.addComponent(buttonsCommentLayout);

		buttonsCommentLayout.addComponent(lengthCommentLabel);
		buttonsCommentLayout.addComponent(infoCommentLabel);
		buttonsCommentLayout.addComponent(postCommentButton);

		buttonsCommentLayout.setComponentAlignment(lengthCommentLabel, Alignment.MIDDLE_CENTER);
		buttonsCommentLayout.setComponentAlignment(postCommentButton, Alignment.MIDDLE_RIGHT);
		buttonsCommentLayout.setMargin(true, false, false, false);

		messageDisplayed = new Label();
		messageDisplayed.setVisible(false);

		postCommentPanel.setEnabled(false);
		postCommentPanel.addComponent(messageDisplayed);
		detailsLayout.addComponent(postCommentPanel);


		inputMessage.focus();
		this.addComponent(messagesLayout);
		this.addComponent(detailsLayout);
		this.setStyleName("stream_bg");

		detailsLayout.setVisible(false);

		HorizontalLayout loadLayout = new HorizontalLayout();
		loadLayout.addComponent(poolMessages);
		loadLayout.setStyleName("invisible");
		loadLayout.setWidth(10, Sizeable.UNITS_PIXELS);

		messagesLayout.addComponent(loadLayout);


		this.setSizeFull();
	}

	/**
	 * @return the streamSearchText
	 */
	public TextField getStreamSearchText() {
		return streamSearchText;
	}

	/**
	 * @return the postPanel
	 */
	public Panel getPostPanel() {
		return postPanel;
	}

	/**
	 * @return the streamFilterBox
	 */
	public NativeSelect getStreamFilterBox() {
		return streamFilterBox;
	}

	/**
	 * @return the messageTable
	 */
	public KernelyMessageTable getMessageTable() {
		return messageTable;
	}

	/**
	 * @return the messageDisplayed
	 */
	public Label getMessageDisplayed() {
		return messageDisplayed;
	}

	/**
	 * @return the postCommentPanel
	 */
	public Panel getPostCommentPanel() {
		return postCommentPanel;
	}

	/**
	 * @return the inputComment
	 */
	public TextField getInputComment() {
		return inputComment;
	}

	/**
	 * @return the postCommentButton
	 */
	public Button getPostCommentButton() {
		return postCommentButton;
	}

	/**
	 * @return the infoCommentLabel
	 */
	public Label getInfoCommentLabel() {
		return infoCommentLabel;
	}

	/**
	 * @return the lengthCommentLabel
	 */
	public Label getLengthCommentLabel() {
		return lengthCommentLabel;
	}

	/**
	 * @return the detailsLayout
	 */
	public VerticalLayout getDetailsLayout() {
		return detailsLayout;
	}

	/**
	 * @return the commentTable
	 */
	public Table getCommentTable() {
		return commentTable;
	}

	/**
	 * @return the streamName
	 */
	public Label getStreamName() {
		return streamName;
	}

	/**
	 * @return the messageContent
	 */
	public Label getMessageContent() {
		return messageContent;
	}

	/**
	 * @return the moreResultLayout
	 */
	public VerticalLayout getMoreResultLayout() {
		return moreResultLayout;
	}

	/**
	 * @return the moreResults
	 */
	public Button getMoreResults() {
		return moreResults;
	}

	/**
	 * @return the infoLabel
	 */
	public Label getInfoLabel() {
		return infoLabel;
	}

	/**
	 * @return the inputMessage
	 */
	public TextField getInputMessage() {
		return inputMessage;
	}

	/**
	 * @return the lengthLabel
	 */
	public Label getLengthLabel() {
		return lengthLabel;
	}

	/**
	 * @return the postButton
	 */
	public Button getPostButton() {
		return postButton;
	}

	/**
	 * Useless method.
	 */
	public Component getComponent() {
		return null;
	}

	/**
	 * Gets the streamSettingsButton
	 * @return the streamSettingsButton
	 */
	public Button getStreamSettingsButton() {
		return streamSettingsButton;
	}

	/**
	 * This method is called when this component is added to an other.
	 */
	@Override
	public void attach(){
		super.attach();
		//When the component is attached, we fire listeners
		StreamBundle.getEventBus().broadcastEvent(new StreamMustDisplayMessagesEvent(this));
	}

	/**
	 * Gets the streamsBox
	 * @return the streamsBox
	 */
	public NativeSelect getStreamsBox() {
		return streamsBox;
	}


	/**
	 * @return the commentableMessage
	 */
	public CheckBox getCommentableMessage() {
		return commentableMessage;
	}
}
